//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "InvoiceReport2.h"
#include "StringUtilities.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

//---------------------------------------------------------------------------

TInvoiceReport :: TInvoiceReport( TDatabase * database)
{
   qryInvoices = new TQuery( NULL);
   qryInvoices->DatabaseName = database->DatabaseName;

   qryTotalAmount = new TQuery( NULL);
   qryTotalAmount->DatabaseName = database->DatabaseName;

   BuildQuery();
}

TInvoiceReport :: ~TInvoiceReport()
{
   delete qryTotalAmount;
   delete qryInvoices;
}

void TInvoiceReport :: BuildQuery()
{
   qryInvoices->SQL->Add( "SELECT INVOICES.ID, INVOICES.PAGEID, INVOICES.INVOICEID, INVOICES.AMOUNT, INVOICES.PAYMENTTYPE, INVOICES.CREATIONDATE, INVOICES.CANCELED, PAYMENTTYPES.ID AS PAYMENTTYPEID, PAYMENTTYPES.DESCRIPTION FROM INVOICES, PAYMENTTYPES");
   qryInvoices->SQL->Add( "WHERE ( CREATIONDATE >= :prmFromDate) AND ( CREATIONDATE < :prmToDate) AND (INVOICES.PAYMENTTYPE = PAYMENTTYPES.ID)");
   qryInvoices->SQL->Add( "ORDER BY CREATIONDATE, PAGEID, INVOICEID");

   qryTotalAmount->SQL->Add( "SELECT SUM( AMOUNT) AS TOTALAMOUNT FROM INVOICES");
   qryTotalAmount->SQL->Add( "WHERE ( CREATIONDATE >= :prmFromDate) AND ( CREATIONDATE < :prmToDate) AND ( CANCELED = :prmCanceled)");
}

TQuery * TInvoiceReport :: GetQuery()
{
   return qryInvoices;
}

TQuery * TInvoiceReport :: GetTotalAmountQuery()
{
   return qryTotalAmount;
}

void TInvoiceReport :: Produce( int year, int month)
{
   TDateTime fromDate;
   TDateTime toDate;

   this->year = year;
   isLastMonth = ( month == 12);
   fromDate   = EncodeDate( year, month, 1);
   toDate     = IncMonth( fromDate, 1);

   qryInvoices->ParamByName( "prmFromDate")->AsDate = fromDate;
   qryInvoices->ParamByName( "prmToDate")->AsDate   = toDate;

   qryInvoices->Open();
}

void TInvoiceReport :: Close()
{
   qryTotalAmount->Close();
   qryInvoices->Close();
}


//---------------------------------------------------------------------------


TBandData :: TBandData()
{
   sorter    = new TStringList();
   cancelled = new TStringList();
   Clear();
}

TBandData :: ~TBandData()
{
   delete cancelled;     
   delete sorter;
}

void TBandData :: Clear()
{
   date.current = 0;
   date.current = 0;
   date.show    = true;
   page.value   = 0;
   page.amount  = 0;
   sorter->Clear();
   cancelled->Clear();
}

void TBandData :: Add( TInvoice* invoice)
{
   page.value = invoice->page;
   page.amount += invoice->amount;
   sorter->Add( IntToStr( invoice->invoiceID));
   if ( invoice->isCanceled)
      cancelled->Add( IntToStr( invoice->invoiceID));
   date.previous = date.current;
   date.current  = invoice->date;
}

bool TBandData :: IsCompleted( TInvoice* invoice)
{
   if ((( double)date.current != 0) && ( date.current != invoice->date))
      return true;

   if (( page.value != 0) && ( page.value != invoice->page))
      return true;

   return false;
}

//---------------------------------------------------------------------------

TTotalData::TTotalData()
{
   totalPayments = new TStringList();
   Clear();
}

TTotalData::~TTotalData()
{
   TStringUtilites::Clear(totalPayments);   
}

void TTotalData::Clear()
{
   regularAmount   = 0;
   cancelledAmount = 0;
   yearAmount      = 0;
   TStringUtilites::Clear(totalPayments);
}


__fastcall TfrmInvoiceReport::TfrmInvoiceReport(TComponent* Owner, TDatabase* dbMain)
        : TForm(Owner)
{
   invoiceReport = new TInvoiceReport(dbMain);
   bandData  = new TBandData();
   totalData = new TTotalData();
   printedDate   = 0;
   printedPage   = 0;
   ptb = new TPaymentTypeBridge(dbMain);
   PreparePaymentTypes();
}

void __fastcall TfrmInvoiceReport::FormDestroy(TObject *Sender)
{
   delete ptb;
   delete totalData;
   delete bandData;
   delete invoiceReport;
}

void TfrmInvoiceReport::PreparePaymentTypes()
{
   int top  = lblTotalCancelledAmount->Top + 24;
   int left = lblTotalCancelledAmount->Left;

   TStringList* paymentTypes = new TStringList();

   try
   {
      ptb->GetPaymentTypes(paymentTypes);

      for (int i = 0; i < paymentTypes->Count; i++)
      {
         TPaymentType* pt = (TPaymentType*)paymentTypes->Objects[i];

         TQRLabel* lblMPT = new TQRLabel(bndSummary);
         lblMPT->Top = top;
         lblMPT->Left = left;
         lblMPT->Width = 90;
         lblMPT->Parent = bndSummary;
         lblMPT->Font->Style = TFontStyles() << fsBold;
         lblMPT->Font->Size = 10;
         lblMPT->Caption = "Total monthly amount by ";
         lblMPT->Caption = lblMPT->Caption + pt->description + ":";

         TQRLabel* lblMPTV = new TQRLabel(bndSummary);
         lblMPTV->Name = "lblMPTV" + IntToStr(pt->id);
         lblMPTV->Top = lblMPT->Top;
         lblMPTV->Left = lblTotalAmountValue->Left;
         lblMPTV->Parent = bndSummary;
         lblMPTV->Caption = CurrencyString + " 0";

         top = lblMPT->Top + 24;
      }

      lblTotalMonthlyAmount->Top = top;
      lblTotalMonthlyAmountValue->Top = lblTotalMonthlyAmount->Top;
      lblYearAmount->Top = lblTotalMonthlyAmount->Top + 24;
      lblTotalYearAmountValue->Top = lblYearAmount->Top;
   }
   __finally
   {
      TStringUtilites::Clear(paymentTypes);
      delete paymentTypes;
   }//try-finally
}

void TfrmInvoiceReport :: Preview( int year, int month)
{
   lblYearAmount->Visible = ( month == 12);
   lblTotalYearAmountValue->Visible = lblYearAmount->Visible;

   invoiceReport->Produce( year, month);

   try
   {
      qrInvoices->Preview();
   }
   __finally
   {
      invoiceReport->Close();
   }
}

double TfrmInvoiceReport::getYearAmount()
{
   TQuery * qryYearAmount;
   TDateTime fromDate;
   TDateTime toDate;

   qryYearAmount = invoiceReport->GetTotalAmountQuery();
   
   fromDate = EncodeDate( invoiceReport->year, 1, 1);
   toDate   = IncMonth( fromDate, 12);
   qryYearAmount->ParamByName( "prmFromDate")->AsDate   = fromDate;
   qryYearAmount->ParamByName( "prmToDate")->AsDate     = toDate;
   qryYearAmount->ParamByName( "prmCanceled")->AsString = TStringUtilites :: BooleanToYN( false);

   qryYearAmount->Open();

   try
   {
      if ( !qryYearAmount->Eof)
         return qryYearAmount->FieldByName( "TOTALAMOUNT")->AsFloat;
   }
   __finally
   {
      qryYearAmount->Close();
   }//try-finally

   return 0;
}

void __fastcall TfrmInvoiceReport::bndSummaryBeforePrint(
      TQRCustomBand *Sender, bool &PrintBand)
{
   lblTotalAmountValue->Caption          = CurrencyString + " " + FloatToStr( totalData->regularAmount);
   lblTotalCancelledAmountValue->Caption = CurrencyString + " " + FloatToStr( totalData->cancelledAmount);
   lblTotalMonthlyAmountValue->Caption   = CurrencyString + " " + FloatToStr( totalData->regularAmount - totalData->cancelledAmount);

   for (int i = 0; i < totalData->totalPayments->Count; i++)
   {
      TTotalMonthlyPayment* tmp = (TTotalMonthlyPayment*)totalData->totalPayments->Objects[i];

      AnsiString lblName = "lblMPTV" + IntToStr(tmp->paymentID);
      TQRLabel* lblPaymentTypeValue = (TQRLabel*)bndSummary->FindComponent(lblName);
      if (lblPaymentTypeValue != NULL)
      {
         lblPaymentTypeValue->Caption = CurrencyString + " " + FloatToStr(tmp->amount);
      }
   }

   if ( lblYearAmount->Visible)
   {
      lblTotalYearAmountValue->Caption = CurrencyString + " " + FloatToStr( getYearAmount());
   }
   else
   {
      lblYearAmount->Caption           = "";
      lblTotalYearAmountValue->Caption = "";
   }

   totalData->Clear();
}



void __fastcall TfrmInvoiceReport::txtStatusPrint(TObject *sender,
      AnsiString &Value)
{
   if ( Value == "Y")
      Value = "Cancelled";
   else
      Value = "OK";   
}

void TfrmInvoiceReport::PrintBandData()
{
   int i;
   
   lblDateValue->Visible = bandData->date.show;   
   if ( lblDateValue->Visible)
      lblDateValue->Caption = DateToStr( bandData->date.current);

   lblPageValue->Caption    = IntToStr( bandData->page.value);

   lblInvoiceValue->Caption = bandData->sorter->Strings[ 0];

   if ( bandData->sorter->Count > 1)
      lblInvoiceValue->Caption = lblInvoiceValue->Caption + " - " + bandData->sorter->Strings[ bandData->sorter->Count - 1];

   lblAmountValue->Caption = CurrencyString + " " + FloatToStr( bandData->page.amount);

   lblCancelledValue->Caption = "";
   if ( bandData->cancelled->Count > 0)
      lblCancelledValue->Caption = bandData->cancelled->Strings[ 0];

   for ( i = 1; i < bandData->cancelled->Count; i++)
      lblCancelledValue->Caption = lblCancelledValue->Caption + "," + bandData->cancelled->Strings[ i];
}

void __fastcall TfrmInvoiceReport::qrInvoicesNeedData(TObject *Sender,
      bool &MoreData)
{
   bool bandCompleted;
   TInvoice * invoice;

   MoreData = !invoiceReport->GetQuery()->Eof;

   if ( MoreData)
   {
      bandData->Clear();
      bandCompleted = false;

      invoice = new TInvoice();

      try
      {
         while (( !invoiceReport->GetQuery()->Eof) && ( !bandCompleted))
         {
            invoice->date = invoiceReport->GetQuery()->FieldByName( "CREATIONDATE")->AsDateTime;
            invoice->page = invoiceReport->GetQuery()->FieldByName( "PAGEID")->AsInteger;
            invoice->invoiceID  = invoiceReport->GetQuery()->FieldByName( "INVOICEID")->AsInteger;
            invoice->amount     = invoiceReport->GetQuery()->FieldByName( "AMOUNT")->AsFloat;
            invoice->isCanceled = TStringUtilites :: YNToBoolean( invoiceReport->GetQuery()->FieldByName( "CANCELED")->AsString);
            invoice->paymentType->id = invoiceReport->GetQuery()->FieldByName( "PAYMENTTYPEID")->AsInteger;
            invoice->paymentType->description = invoiceReport->GetQuery()->FieldByName( "DESCRIPTION")->AsString;

            bandCompleted = bandData->IsCompleted( invoice);

            if ( bandCompleted)
            {
               PrintBandData();
            }
            else
            {
               bandData->Add( invoice);

               if ( invoice->isCanceled)
               {
                  totalData->cancelledAmount += invoice->amount;
               }
               else
               {
                  int index = totalData->totalPayments->IndexOf(IntToStr(invoice->paymentType->id));
                  if (index == -1)
                  {
                     TTotalMonthlyPayment* tmp = new TTotalMonthlyPayment();
                     tmp->paymentID = invoice->paymentType->id;
                     tmp->amount = invoice->amount;
                     totalData->totalPayments->AddObject(tmp->paymentID, tmp);
                  }
                  else
                  {
                     TTotalMonthlyPayment* tmp = (TTotalMonthlyPayment*)totalData->totalPayments->Objects[index];
                     tmp->amount += invoice->amount;
                  }
               }

               totalData->regularAmount += invoice->amount;

               invoiceReport->GetQuery()->Next();
            }
         }//while

         if ( invoiceReport->GetQuery()->Eof)
            PrintBandData();
      }
      __finally
      {
         delete invoice;
      }//try-finally
   }//if
}
//---------------------------------------------------------------------------



void __fastcall TfrmInvoiceReport::qrInvoicesBeforePrint(
      TCustomQuickRep *Sender, bool &PrintReport)
{
   //reset the query set to point first record
   //to print the report (must be done manually, because
   //qrInvoicesNeedData is implemented and cause the query set to point
   //to last record
   invoiceReport->GetQuery()->First();
}
//---------------------------------------------------------------------------





